<?php

namespace App\Command;

use EasySwoole\Command\AbstractInterface\CommandHelpInterface;
use EasySwoole\Command\CommandManager;

/**
 * Class BaseCommand
 * 自定义命令行基类，
 * 继承此类所写的自定义命令时，调用命令就是该类的保护方法，参数以--var命令行参数传入，以,分隔；
 * 方法的说明，则使用类方法的注释文档备注
 * 添加新的自定义命令时，需要在bootstrap.php文件进行注册
 * @package App\Command
 */
abstract class BaseCommand implements \EasySwoole\Command\AbstractInterface\CommandInterface{
    
    public function commandName() : string{
        $class = new  \ReflectionClass($this);
        $className = strtolower($class->getShortName());
        return $className;
    }
    
    abstract public function desc() : string;
    
    /**
     * 执行方法，运行相应的需要执行的命令
     * @return string|null
     */
    public function exec() : ?string{
        // TODO: Implement exec() method.
        
        $args = CommandManager::getInstance()->getArgs();
        
        if(count($args) <> 1){
            echo "请输出需要执行的方法，或可使用 -h 查看" . PHP_EOL;
            return null;
        }
        
        // 下面就是对 自定义命令 的一些处理逻辑
        $action = $args[0];
        if(!$action){
            echo "请输出需要执行的方法，或可使用 -h 查看" . PHP_EOL;
            return null;
        }
        
        if(!method_exists($this, $action)){
            echo "不存在该方法，请使用-h查看相关可执行的方法" . PHP_EOL;
        }
        
        //解释参数
        $optionVar = CommandManager::getInstance()->getOpt('var');
        $optionArr = explode(',', $optionVar);
        array_map('trim', $optionArr);
        //执行方法
        call_user_func_array([$this, $action], $optionArr);
        
        return null;
        
    }
    
    /**
     * 帮助说明，以及绑定的参数
     * @param CommandHelpInterface $commandHelp
     * @return CommandHelpInterface
     */
    public function help(CommandHelpInterface $commandHelp) : CommandHelpInterface{
        
        // 添加 自定义action(action 名称及描述)
        $class = new  \ReflectionClass($this);
        $methods = $class->getMethods();
        foreach($methods as $v){
            //私有方法都认为是可调用的方法
            if($v->isProtected()){
                $docCommentArr = $v->getDocComment() ? explode("\n", $v->getDocComment()) : [];
                $desc = trim(substr(trim($docCommentArr[1] ?? ''), 1));
                $commandHelp->addAction($v->getName(), $desc);
            }
        }
        
        // 添加 自定义action 可选参数
        $commandHelp->addActionOpt('--var=str_value', '传参，str_value值以【,】分隔，以对应调用方法的不同的参数');
        return $commandHelp;
    }
}